package com.blocks.controller;

import com.blocks.ScriptBlocksApplication;
import com.blocks.ScriptBlocksApplication.GameState;
import com.blocks.blocks.Block;
import com.blocks.blocks.MasterBlock;
import com.blocks.blocks.ScriptEvaluator;
import com.blocks.model.BlockSides;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;

public class BlockActionListener implements AnalogListener, ActionListener {

	int blockNumber = 0;

	public void onAction(String name, boolean keyPressed, float tpf) {
		ScriptBlocksApplication app = ScriptBlocksApplication.getInstance();
		if (app.getGameState() == GameState.GAME) {
			if (name.equals("Menu") && !keyPressed) {
				if(app.getGameState()!= GameState.GUI){
					app.initNiftyGui();				
				}
			} else if (name.equals("Terminal") && !keyPressed) {
				if(app.getGameState()!= GameState.GUI){
					app.initNiftyTerminal();
				}
			} else if (name.equals("Inventory") && !keyPressed) {
				if(app.getGameState()!= GameState.GUI){
				app.initNiftyInventory();
				}
			} else if (name.equals("Help") && !keyPressed) {
				if(app.getGameState()!= GameState.GUI){
					app.initNiftyHelp();
				}

			}else if (name.equals("shootRight") && !keyPressed) {
				place(name);
			}

			else if (name.equals("Use") && !keyPressed) {
				shootNode(name);
			} else if (name.equals("Shoot") && !keyPressed) {
				app.shoot(
						ScriptBlocksApplication
								.getInstance()
								.getCam()
								.getLocation()
								.add(app
										.getCam().getDirection()));
			} else if (name.equals("Lefts")) {
				if (keyPressed) {
					app.setLeft(true);
				} else {
					app.setLeft(false);
				}
			} else if (name.equals("Rights")) {
				if (keyPressed) {
					app.setRight(true);
				} else {
					app.setRight(false);
				}
			} else if (name.equals("Ups")) {
				if (keyPressed) {
					app.setUp(true);
				} else {
					app.setUp(false);
				}
			} else if (name.equals("Downs")) {
				if (keyPressed) {
					app.setDown(true);
				} else {
					app.setDown(false);
				}
			} else if (name.equals("Remove") && !keyPressed) {
				app.copyHiearchyBeforeRemove();	
				remove();
			} else if (name.equals("Fly") && !keyPressed) {
				if (app.isFly()) {
					app.playerWalk();
				} else {
					app.playerFly();

				}
			} else if (name.equals("BlockLeft")) {
				if (app.getLevelProperties().isMoveBlockX() && keyPressed) {
					app.setBlockLeft(true);
				} else {
					app.setBlockLeft(false);
				}
			} else if (name.equals("BlockRight")) {
				if (app.getLevelProperties().isMoveBlockX() && keyPressed) {
					app.setBlockRight(true);
				} else {
					app.setBlockRight(false);
				}

			} else if (name.equals("BlockForward")) {
				if (app.getLevelProperties().isMoveBlockZ() && keyPressed) {
					app.setBlockForward(true);
				} else {
					app
							.setBlockForward(false);
				}

			} else if (name.equals("BlockBackward")) {
				if (app.getLevelProperties().isMoveBlockZ() && keyPressed) {
					app
							.setBlockBackward(true);
				} else {
					app.setBlockBackward(
							false);
				}
			} else if (name.equals("BlockUp")) {
				if (app.getLevelProperties().isMoveBlockY() && keyPressed) {
					app.setBlockUp(true);
				} else {
					app.setBlockUp(false);
				}
			} else if (name.equals("BlockDown")) {
				if (app.getLevelProperties().isMoveBlockY() && keyPressed) {
					app.setBlockDown(true);
				} else {
					app.setBlockDown(false);
				}
			} else if (name.equals("BlockPower") && !keyPressed) {
				Block block = app
						.getMasterMoveBlock();
				if (block != null && block instanceof MasterBlock) {
					MasterBlock masterBlock = (MasterBlock) block;
					masterBlock.use();
				}
			} else if (name.equals("Inventory1") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(1));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory2") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(2));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory3") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(3));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory4") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(4));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory5") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(5));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory6") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(6));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory7") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(7));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory8") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(8));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory9") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(9));
				BlockUtils.updateHUDBlock();
			} else if (name.equals("Inventory0") && !keyPressed) {
				app.setHudBlockIndex(
						new Long(0));
				BlockUtils.updateHUDBlock();
			}
			else if (name.equals("Copy") && !keyPressed) {
				app.copyHiearcy();			
			}
			else if (name.equals("Paste") && !keyPressed) {
				app.pasteHiearcy();			
			}
			else if (name.equals("Undo") && !keyPressed) {
				
				app.undoHiearchy();			
			}
		}
	}

	private void remove() {
		if (ScriptBlocksApplication.getInstance().getFocusBlock() != null
				&& ScriptBlocksApplication.getInstance().getFocusBlock()
						.isPowered()) {
			return;
		}
		if (ScriptBlocksApplication.getInstance().getFocusBlock() != null
				&& !(ScriptBlocksApplication.getInstance().getFocusBlock() instanceof MasterBlock)) {
			Node parentNode = ScriptBlocksApplication.getInstance()
					.getFocusBlock().getParent();
			Long masterId = ScriptBlocksApplication.getInstance()
					.getFocusBlock().getMasterId();
			if (parentNode != null) {
				parentNode.detachChild(ScriptBlocksApplication.getInstance()
						.getFocusBlock());
			}

		}
		if (ScriptBlocksApplication.getInstance().getFocusBlock() != null
				&& (ScriptBlocksApplication.getInstance().getFocusBlock() instanceof MasterBlock)) {
			MasterBlock masterBlock = (MasterBlock) ScriptBlocksApplication
					.getInstance().getFocusBlock();

			ScriptBlocksApplication.getInstance().getRootNode().getChildren()
					.remove(masterBlock);
			ScriptBlocksApplication.getInstance().getMasterBlockMap()
					.remove(masterBlock.getMasterId());
		}
	}

	// Right Click should place the block
	private void place(String name) {
		if (ScriptBlocksApplication.getInstance().getFocusBlock() != null
				&& ScriptBlocksApplication.getInstance().getFocusBlock()
						.isPowered()) {
			return;
		}
		if (ScriptBlocksApplication.getInstance().getFocusBlock() != null) {
			Block focusBlock = ScriptBlocksApplication.getInstance()
					.getFocusBlock();

			MasterBlock masterBlock = ScriptBlocksApplication.getInstance()
					.getMasterBlock(focusBlock.getMasterId());
			if(masterBlock!=null){
				String childBlockName = masterBlock.getName()
						+ masterBlock.getChildCount();
	
				Block shotBlock = ScriptBlocksApplication.getInstance()
						.getNewBlock(childBlockName);
	
				if (shotBlock != null) {
					shotBlock.init();
					shotBlock.setLocalTranslation(ScriptBlocksApplication
							.getInstance().getFocusBlock().getLocalTranslation()
							.add(new Vector3f(0.0f, 2.0f, 0.0f)));
					int focusBlockTriangle = ScriptBlocksApplication.getInstance()
							.getFocusBlockTriangle();
					BlockSides focuseBlockSides = BlockSides
							.getBlockSideFromTriangle(focusBlockTriangle);
					shotBlock.setBlockSides(focuseBlockSides);
					Vector3f vector = BlockUtils.calculatePivot(focuseBlockSides);
	
					focusBlock.attachChild(shotBlock);
					shotBlock.setName(focusBlock.getName() + "_"
							+ shotBlock.getName() + shotBlock.getBlockSides());
					shotBlock.setLocalTranslation(vector);
				}
			}else {
				System.out.println("BLock Action Listener.place master block is null");
			}
		}

	}

	public void shootNode(String name) {

		CollisionResults results = new CollisionResults();

		Ray ray = new Ray(ScriptBlocksApplication.getInstance().getCam()
				.getLocation(), ScriptBlocksApplication.getInstance().getCam()
				.getDirection());

		ScriptBlocksApplication.getInstance().getRootNode()
				.collideWith(ray, results);

		for (int i = 0; i < results.size(); i++) {

		}

		if (results.size() > 0) {

			CollisionResult closest = results.getClosestCollision();

			if ("Use".equals(name)) {
				Block focusBlock = ScriptBlocksApplication.getInstance()
						.getFocusBlock();
				if (focusBlock != null
						&& Block.class.isAssignableFrom(focusBlock.getClass())) {
					focusBlock.use();
					ScriptBlocksApplication
							.getInstance()
							.getAudioRenderer()
							.playSource(
									ScriptBlocksApplication.getInstance()
											.getAudioGun()); // play
																// once!
				}else {
					System.out.println("BlockActionListener.shoot focus block =" + focusBlock);
				}
			}

		}
	}

	// Some tests
	private Vector3f calculateAxis(BlockSides blockSides) {
		if (BlockSides.SIDE_ABOVE == blockSides) {
			return Vector3f.UNIT_Y;
		}
		if (BlockSides.SIDE_BELOW == blockSides) {
			return Vector3f.UNIT_Y;
		}
		if (BlockSides.SIDE_FRONT == blockSides) {
			return Vector3f.UNIT_Z;
		}
		if (BlockSides.SIDE_BACK == blockSides) {
			return Vector3f.UNIT_Z;
		}
		if (BlockSides.SIDE_LEFT == blockSides) {
			return Vector3f.UNIT_X;
		}
		if (BlockSides.SIDE_RIGHT == blockSides) {
			return Vector3f.UNIT_X;
		}

		return Vector3f.ZERO;
	}

	public void weld(Block blk1, Block blk2, BlockSides blockSides1,
			BlockSides blockSides2) {
		if (blk1 == null || blk2 == null) {
			System.out.println("You must pick two blocks");
		}

		blk1.removeControl(RigidBodyControl.class);
		blk2.removeControl(RigidBodyControl.class);
		blk1.setLocalRotation(Matrix3f.ZERO);

		Vector3f yawRollPitch = BlockUtils.calculateRotation(blockSides1,
				blockSides2);
		float yaw = yawRollPitch.getX();
		float roll = yawRollPitch.getY();
		float pitch = yawRollPitch.getZ();
		blk2.setLocalRotation(Quaternion.ZERO.fromAngles(yaw, roll, pitch));
		// blk2.setLocalRotation(blk1.getLocalRotation());
		Vector3f vector = BlockUtils.calculatePivot(blockSides1);
		blk2.setLocalTranslation(blk1.getLocalTranslation().add(vector));

	}

	@Override
	public void onAnalog(String name, float value, float tpf) {
		if (ScriptBlocksApplication.getInstance().getGameState() == GameState.GAME) {
			if (name.equals("MoveMouse")) {
				// Block oldFocus = ScriptBlocksApplication.getInstance()
				// .getFocusBlock();
				// if (oldFocus != null) {
				// ScriptBlocksApplication.getInstance().getFocusBlock()
				// .unmarkBlock();
				// }
				// focus();
			}
			if (name.equals("MoveMouseWheelNegative")) {
				if (ScriptBlocksApplication.getInstance().getHudBlockIndex() > 0) {
					ScriptBlocksApplication.getInstance().setHudBlockIndex(
							ScriptBlocksApplication.getInstance()
									.getHudBlockIndex() - 1);
				} else {
					ScriptBlocksApplication.getInstance().setHudBlockIndex(
							new Long(ScriptBlocksApplication.getInstance()
									.getBlockTypeMap().size() - 1));
				}

				BlockUtils.updateHUDBlock();
			}
			if (name.equals("MoveMouseWheel")) {

				ScriptBlocksApplication.getInstance().setHudBlockIndex(
						(ScriptBlocksApplication.getInstance()
								.getHudBlockIndex() + 1)
								% ScriptBlocksApplication.getInstance()
										.getBlockTypeMap().size());
				BlockUtils.updateHUDBlock();
			}
		}
	}

	public void focus() {
		CollisionResults results = new CollisionResults();		
		Ray ray = new Ray(ScriptBlocksApplication.getInstance().getCam()
				.getLocation(), ScriptBlocksApplication.getInstance().getCam()
				.getDirection());
		ray.setLimit(100.0f);
		ScriptBlocksApplication.getInstance().getRootNode()
				.collideWith(ray, results);
		if (results.size() > 0) {
			for (CollisionResult result : results) {
				if (result.getGeometry() != null) {
					Node hitNode = result.getGeometry().getParent();
					int triangle = result.getTriangleIndex();					
					float distance = result.getDistance();
					if (distance <= ScriptBlocksApplication.FOCUS_DISTANCE
							&& hitNode != null) {
						Object parent = hitNode;
						if (parent != null
								&& Block.class.isAssignableFrom(parent
										.getClass())) {							
							Block focusBlock = (Block) parent;
							{
								Block oldFocus = ScriptBlocksApplication
										.getInstance().getFocusBlock();
								if (oldFocus != null
										&& !oldFocus.equals(focusBlock)) {
									oldFocus.unmarkBlock();
								}
							}
							focusBlock.markBlock();
							ScriptBlocksApplication.getInstance()
									.setFocusBlock(focusBlock);
							ScriptBlocksApplication.getInstance()
									.setFocusBlockTriangle(triangle);
							if (focusBlock instanceof MasterBlock) {
								ScriptBlocksApplication.getInstance()
										.setMasterMoveBlock(focusBlock);
							}
							break;	
						}
						
					}

				}
			}
		}
		

	}

	private void unfocus() {
		Block oldFocus = ScriptBlocksApplication.getInstance().getFocusBlock();
		if (oldFocus != null) {
			oldFocus.unmarkBlock();
			ScriptBlocksApplication.getInstance().setFocusBlock(null);
			ScriptBlocksApplication.getInstance().setFocusBlockTriangle(-1);
		}
	}

	public float hudBoxXScale() {
		return ScriptBlocksApplication.getInstance().getContext().getSettings()
				.getWidth() / 11;
	}

	public float hudBoxYScale() {
		return ScriptBlocksApplication.getInstance().getContext().getSettings()
				.getHeight() / 30;
	}
}
